/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
 * vim: set ts=8 sw=4 et tw=0 ft=C:
 *
 * ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is SpiderMonkey nanojit.
 *
 * The Initial Developer of the Original Code is
 * the Mozilla Corporation.
 * Portions created by the Initial Developer are Copyright (C) 2008
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *   Jeff Walden <jwalden+code@mit.edu>
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either of the GNU General Public License Version 2 or later (the "GPL"),
 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

/*
 * Definitions of LIR opcodes.  If you need to allocate an opcode, look
 * for a name of the form unused* and claim it.
 *
 * Includers must define OPDEF and OPDEF64 macros of the following forms:
 *
 * #define   OPDEF(op,val,operands,repkind) ...
 * #define OPDEF64(op,val,operands,repkind) ...
 *
 * Selected arguments can then be used within the macro expansions.
 *
 * Field        Description
 * op           Bytecode name, token-pasted after "LIR_" to form an LOpcode.
 * val          Bytecode value, which is the LOpcode enumerator value.
 * operands     Number of operands for this instruction, where an "operand" is
 *              a LIns* argument.  Eg. LIR_sti has 3 fields, but the last is an
 *              immediate, so it only has two operands.  Call instructions are
 *              considered to have 0 operands -- the call args aren't counted.
 *              The value is set to -1 for unused opcodes to make it obvious
 *              that it needs changing if the opcode becomes used.
 * repkind      Indicates how the instruction is represented in memory;  XYZ
 *              corresponds to LInsXYZ and LRK_XYZ.
 *
 * This file is best viewed with 128 columns:
12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678
 *
 * Aliases for pointer-sized operations that choose 32bit or 64bit instructions
 * are given in the LOpcode enum in LIR.h just after including LIRopcodes.tbl.
 */

/*    op    val name        operands */

/* special operations (must be 0..N) */
OPDEF(start,     0, 0, Op0)     // start of a fragment
OPDEF(regfence,  1, 0, Op0)     // register fence, no register allocation is allowed across this meta instruction
OPDEF(skip,      2, 1, Sk)      // holds blobs ("payloads") of data;  also links pages
OPDEF(unused3,   3,-1, None)
OPDEF(unused4,   4,-1, None)
OPDEF(unused5,   5,-1, None)
OPDEF(unused6,   6,-1, None)

/* non-pure operations */
OPDEF(iaddp,     7, 2, Op2)     // integer addition for temporary pointer calculations (32bit only)
OPDEF(iparam,    8, 0, P)       // load a parameter (32bit register or stk location)
OPDEF(unused9,   9,-1, None)
OPDEF(ld,       10, 1, Ld)      // 32-bit load
OPDEF(ialloc,   11, 0, I)       // alloc some stack space (value is 32bit address)
OPDEF(sti,      12, 2, Sti)     // 32-bit store
OPDEF(ret,      13, 1, Op1)     // return a word-sized value
OPDEF(live,     14, 1, Op1)     // extend live range of reference
OPDEF(flive,    15, 1, Op1)     // extend live range of a floating point value reference
OPDEF(icall,    16, 0, C)       // subroutine call returning a 32-bit value
OPDEF(unused17, 17, 0, None)

/* guards */
OPDEF(x,        18, 0, Op2)     // exit always

/* branches */
OPDEF(j,        19, 0, Op2)     // jump always
OPDEF(jt,       20, 1, Op2)     // jump if true
OPDEF(jf,       21, 1, Op2)     // jump if false
OPDEF(label,    22, 0, Op0)     // a jump target (no machine code is emitted for this)
OPDEF(ji,       23,-1, None)    // indirect jump (currently not implemented)

/* operators */

/*
 * NB: Opcodes LIR_int through LIR_uge must remain continuous to aid in
 *     common-subexpression-elimination detection code.
 */

OPDEF(int,      24, 0, I)       // constant 32-bit integer
OPDEF(cmov,     25, 3, Op3)     // conditional move
OPDEF(callh,    26, 1, Op1)     // get the high 32 bits of a call returning a 64-bit value in two 32bit registers

/*
 * feq though fge must only be used on float arguments.  They return integers.
 * For all except feq, (op ^ 1) is the op which flips the
 * left and right sides of the comparison, so (lt ^ 1) == gt, or the operator
 * "<" is xored with 1 to get ">".  Similarly, (op ^ 3) is the complement of
 * op, so (lt ^ 1) == ge, or the complement of the operator "<" is ">=" xored
 * with 3.  NB: These opcodes must remain continuous so that comparison-opcode
 * detection works correctly.
 */
OPDEF(feq,      27, 2, Op2)     // floating-point equality
OPDEF(flt,      28, 2, Op2)     // floating-point less-than
OPDEF(fgt,      29, 2, Op2)     // floating-point greater-than
OPDEF(fle,      30, 2, Op2)     // floating-point less-than-or-equal
OPDEF(fge,      31, 2, Op2)     // floating-point greater-than-or-equal

OPDEF(ldcb,     32, 1, Ld)      // non-volatile  8-bit load
OPDEF(ldcs,     33, 1, Ld)      // non-volatile 16-bit load
OPDEF(ldc,      34, 1, Ld)      // non-volatile 32-bit load

OPDEF(neg,      35, 1, Op1)     // integer negation
OPDEF(add,      36, 2, Op2)     // integer addition
OPDEF(sub,      37, 2, Op2)     // integer subtraction
OPDEF(mul,      38, 2, Op2)     // integer multiplication
OPDEF(div,      39, 2, Op2)     // integer division
OPDEF(mod,      40, 1, Op1)     // hack: get the modulus from a LIR_div result, for x86 only

OPDEF(and,      41, 2, Op2)     // 32-bit bitwise AND
OPDEF(or,       42, 2, Op2)     // 32-bit bitwise OR
OPDEF(xor,      43, 2, Op2)     // 32-bit bitwise XOR
OPDEF(not,      44, 1, Op1)     // 32-bit bitwise NOT
OPDEF(lsh,      45, 2, Op2)     // 32-bit left shift
OPDEF(rsh,      46, 2, Op2)     // 32-bit right shift with sign-extend (>>)
OPDEF(ush,      47, 2, Op2)     // 32-bit unsigned right shift (>>>)

// conditional guards, op^1 to complement.  Only things that are
// isCond() can be passed to these.
OPDEF(xt,       48, 1, Op2)     // exit if true   (0x30 0011 0000)
OPDEF(xf,       49, 1, Op2)     // exit if false  (0x31 0011 0001)

OPDEF(qlo,      50, 1, Op1)     // get the low  32 bits of a 64-bit value
OPDEF(qhi,      51, 1, Op1)     // get the high 32 bits of a 64-bit value

OPDEF(unused52, 52,-1, None)
OPDEF(unused53, 53,-1, None)

// This must be right before LIR_eq, so (op&~LIR64 - LIR_ov) can be indexed
// into a convenient table.
OPDEF(ov,       54, 1, Op1)     // test for overflow;  value must have just been computed

// Integer (32 bit) relational operators.  (op ^ 1) is the op which flips the
// left and right sides of the comparison, so (lt ^ 1) == gt, or the operator
// "<" is xored with 1 to get ">".  Similarly, (op ^ 3) is the complement of
// op, so (lt ^ 1) == ge, or the complement of the operator "<" is ">=" xored
// with 3.  'u' prefix indicates the unsigned integer variant.
// NB: These opcodes must remain continuous so that comparison-opcode detection
// works correctly.
OPDEF(eq,       55, 2, Op2)     //          integer equality
OPDEF(lt,       56, 2, Op2)     //   signed integer less-than             (0x38 0011 1000)
OPDEF(gt,       57, 2, Op2)     //   signed integer greater-than          (0x39 0011 1001)
OPDEF(le,       58, 2, Op2)     //   signed integer less-than-or-equal    (0x3A 0011 1010)
OPDEF(ge,       59, 2, Op2)     //   signed integer greater-than-or-equal (0x3B 0011 1011)
OPDEF(ult,      60, 2, Op2)     // unsigned integer less-than             (0x3C 0011 1100)
OPDEF(ugt,      61, 2, Op2)     // unsigned integer greater-than          (0x3D 0011 1101)
OPDEF(ule,      62, 2, Op2)     // unsigned integer less-than-or-equal    (0x3E 0011 1110)
OPDEF(uge,      63, 2, Op2)     // unsigned integer greater-than-or-equal (0x3F 0011 1111)

OPDEF64(unused0_64, 0,-1, None)

OPDEF64(file,       1, 2, Op1)      // source filename for debug symbols
OPDEF64(line,       2, 2, Op1)      // source line number for debug symbols
OPDEF64(xbarrier,   3, 0, Op2)      // memory barrier;  doesn't exit, but flushes all values to the stack
OPDEF64(xtbl,       4, 1, Op2)      // exit via indirect jump

OPDEF64(unused5_64, 5,-1, None)
OPDEF64(unused6_64, 6,-1, None)
OPDEF64(qaddp, LIR_iaddp, 2, Op2)    // integer addition for temp pointer calculations (64bit only)
OPDEF64(qparam,LIR_iparam,0, P)      // load a parameter (64bit register or stk location)
OPDEF64(unused9_64, 9,-1, None)

OPDEF64(ldq,    LIR_ld, 1, Ld)      // 64-bit (quad) load

OPDEF64(qalloc,LIR_ialloc,0, I)      // allocate some stack space (value is 64bit address)

OPDEF64(stqi,   LIR_sti, 2, Sti)    // 64-bit (quad) store
OPDEF64(fret,   LIR_ret, 1, Op1)

OPDEF64(unused14_64, 14,-1, None)
OPDEF64(unused15_64, 15,-1, None)

OPDEF64(fcall,  LIR_icall,  0, C)   // subroutine call returning 64-bit (quad) double value
OPDEF64(qcall,  17,         0, C)   // subroutine call returning 64-bit (quad) integer value

OPDEF64(unused18_64, 18,-1, None)
OPDEF64(unused19_64, 19,-1, None)
OPDEF64(unused20_64, 20,-1, None)
OPDEF64(unused21_64, 21,-1, None)
OPDEF64(unused22_64, 22,-1, None)
OPDEF64(unused23_64, 23,-1, None)

// We strip off the 64 bit flag and compare that the opcode is between LIR_int
// and LIR_uge to decide whether we can CSE the opcode. All opcodes below
// this marker are subject to CSE.

OPDEF64(quad,   LIR_int,  0, I64)   // 64-bit (quad) constant value
OPDEF64(qcmov,  LIR_cmov, 3, Op3)   // 64-bit conditional move

OPDEF64(i2q,    26,      1, Op1)    // sign-extend i32 to i64
OPDEF64(u2q,    27,      1, Op1)    // zero-extend u32 to u64
OPDEF64(i2f,    28,      1, Op1)    // convert a signed 32-bit integer to a float
OPDEF64(u2f,    29,      1, Op1)    // convert an unsigned 32-bit integer to a float

OPDEF64(unused30_64, 30,-1, None)
OPDEF64(unused31_64, 31,-1, None)
OPDEF64(unused32_64, 32,-1, None)
OPDEF64(unused33_64, 33,-1, None)

OPDEF64(ldqc,   LIR_ldc, 1, Ld)     // non-volatile 64-bit load

OPDEF64(fneg,   LIR_neg, 1, Op1)    // floating-point negation
OPDEF64(fadd,   LIR_add, 2, Op2)    // floating-point addition
OPDEF64(fsub,   LIR_sub, 2, Op2)    // floating-point subtraction
OPDEF64(fmul,   LIR_mul, 2, Op2)    // floating-point multiplication
OPDEF64(fdiv,   LIR_div, 2, Op2)    // floating-point division
OPDEF64(fmod,   LIR_mod, 2, Op2)    // floating-point modulus(?)

OPDEF64(qiand,  41,      2, Op2)    // 64-bit bitwise AND
OPDEF64(qior,   42,      2, Op2)    // 64-bit bitwise OR
OPDEF64(qxor,   43,      2, Op2)    // 64-bit bitwise XOR
OPDEF64(unused44_64, 44,-1, None)
OPDEF64(qilsh,  45,      2, Op2)    // 64-bit left shift
OPDEF64(qirsh,  46,      2, Op2)    // 64-bit signed right shift
OPDEF64(qursh,  47,      2, Op2)    // 64-bit unsigned right shift
OPDEF64(qiadd,  48,      2, Op2)    // 64-bit bitwise ADD

OPDEF64(unused49_64, 49,-1, None)
OPDEF64(qjoin,  50,      2, Op2)    // join two 32-bit values (1st arg is low bits, 2nd is high)
OPDEF64(unused51_64, 51,-1, None)
OPDEF64(unused52_64, 52,-1, None)
OPDEF64(unused53_64, 53,-1, None)
OPDEF64(float,  54,    0, I64)

// 64bit equivalents for integer comparisons
OPDEF64(qeq,  LIR_eq,  2, Op2)  //          integer equality
OPDEF64(qlt,  LIR_lt,  2, Op2)  //   signed integer less-than             (0x78 0111 1000)
OPDEF64(qgt,  LIR_gt,  2, Op2)  //   signed integer greater-than          (0x79 0111 1001)
OPDEF64(qle,  LIR_le,  2, Op2)  //   signed integer less-than-or-equal    (0x7A 0111 1010)
OPDEF64(qge,  LIR_ge,  2, Op2)  //   signed integer greater-than-or-equal (0x7B 0111 1011)
OPDEF64(qult, LIR_ult, 2, Op2)  // unsigned integer less-than             (0x7C 0111 1100)
OPDEF64(qugt, LIR_ugt, 2, Op2)  // unsigned integer greater-than          (0x7D 0111 1101)
OPDEF64(qule, LIR_ule, 2, Op2)  // unsigned integer less-than-or-equal    (0x7E 0111 1110)
OPDEF64(quge, LIR_uge, 2, Op2)  // unsigned integer greater-than-or-equal (0x7F 0111 1111)
